home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
msysjour
/
vol07
/
01
/
heappeep
/
hp2.c
< prev
next >
Wrap
Text File
|
1991-12-31
|
15KB
|
455 lines
#include <windows.h>
#include <string.h> // strcat & strlen
#include <dos.h> // FP_OFF macro
#include "hp2.h"
/* brush colors */
#define BLACK 0x000000L
#define MAGENTA 0xFF00FFL
#define BLUE 0xFF0000L
#define YELLOW 0x00FFFFL
#define RED 0x0000FFL
static HBRUSH hbr [7] ,
hbrMAGENTA ,
hbrBLUE ,
hbrRED ,
hbrYELLOW ;
static HFONT hfont ;
typedef struct tagDEFAULTDATASEGMENT
{
HANDLE hinstActive; // instance handle of active app
HWND hwndActive, // window handle of active app
hwndClient; // window we draw bar graph in.
WORD wSize, // size (bytes) of Data Segment.
wStaticData, // size (bytes) of static data.
wStackMax, // size (bytes) of stack size defined in .DEF
wStackUsed, // size (bytes) of stack actually used.
wHeapMoveable, // size (bytes) of heap allocation (moveable).
wHeapFixed, // size (bytes) of heap allocation (fixed).
wHeapFree, // size (bytes) of free space in heap.
wOther, // size (bytes) of remaining allocated space in DS.
wUnused; // size (bytes) of heap unused.
} DEFAULTDATASEGMENT;
static DEFAULTDATASEGMENT DDS ;
void dds_create (HWND hwndClient)
{
HDC hdc = GetDC (hwndClient);
// Create brushes.
//
if (GetDeviceCaps (hdc, NUMCOLORS) == 2)
{
// create pattern brushes for monochrome display
//
hbrMAGENTA = CreateHatchBrush (HS_DIAGCROSS ,BLACK);
hbrBLUE = CreateHatchBrush (HS_BDIAGONAL ,BLACK);
hbrYELLOW = CreateHatchBrush (HS_FDIAGONAL ,BLACK);
hbrRED = CreateHatchBrush (HS_BDIAGONAL ,BLACK);
}
else
{
// create color brushes for color display
//
hbrMAGENTA = CreateSolidBrush (MAGENTA);
hbrBLUE = CreateSolidBrush (BLUE) ;
hbrYELLOW = CreateSolidBrush (YELLOW) ;
hbrRED = CreateSolidBrush (RED) ;
}
hbr [0] = (HBRUSH)GetStockObject (BLACK_BRUSH) ;
hbr [1] = (HBRUSH)GetStockObject (LTGRAY_BRUSH);
hbr [2] = hbrMAGENTA ;
hbr [3] = hbrBLUE ;
hbr [4] = hbrYELLOW ;
hbr [5] = hbrRED ;
hbr [6] = (HBRUSH)GetStockObject (WHITE_BRUSH);
// Create nice display font
//
{
static LOGFONT lf;
lf.lfHeight = 8;
lf.lfWeight = 700;
lf.lfCharSet = ANSI_CHARSET ;
lf.lfQuality = PROOF_QUALITY;
lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
hfont = CreateFontIndirect (&lf);
}
ReleaseDC (hwndClient, hdc);
DDS.hwndClient = hwndClient;
}
void dds_destroy (void)
{
DeleteObject (hbrBLUE) ;
DeleteObject (hbrMAGENTA);
DeleteObject (hbrYELLOW) ;
DeleteObject (hbrRED) ;
DeleteObject (hfont) ;
}
void dds_paint ()
{
RECT rcClient;
long lTextExt;
WORD wTextWidth;
PAINTSTRUCT ps;
BeginPaint (DDS.hwndClient, &ps);
SelectObject (ps.hdc, hfont) ;
SetMapMode (ps.hdc, MM_ANISOTROPIC);
SetWindowOrg (ps.hdc, 0, 0) ;
SetWindowExt (ps.hdc, 1300, 130) ;
/*
* Set viewport to be the entire client area.
*
*/
GetClientRect (DDS.hwndClient, &rcClient);
SetViewportOrg (ps.hdc, 0, 0);
SetViewportExt (ps.hdc, rcClient.right, rcClient.bottom);
/*
* Draw bar : StaticData = BLACK
* Stack = LTGRAY
* Fixed = MAGENTA
* Moveable = YELLOW
* Free = BLUE
* Other = RED
* Unused = WHITE
*
*/
{
int xBar[8] ,
yBar[2] ,
i ,
nMinWidth ;
POINT pt[2];
double dPercentStaticData ,
dPercentStackMax ,
dPercentFixed ,
dPercentMoveable ,
dPercentFree ,
dPercentOther ,
dPercentUnused ,
dDiv = 0xFFFF/1000.; // makes bar 1000 logical units wide
// eg, each 1% is represented by
// 10 logical units.
dPercentStaticData = (double)DDS.wStaticData /dDiv ;
dPercentStackMax = (double)DDS.wStackMax /dDiv ;
dPercentFixed = (double)DDS.wHeapFixed /dDiv ;
dPercentMoveable = (double)DDS.wHeapMoveable /dDiv ;
dPercentFree = (double)DDS.wHeapFree /dDiv ;
dPercentOther = (double)DDS.wOther /dDiv ;
dPercentUnused = (double)DDS.wUnused /dDiv ;
// Compute a logical width that corresponds to a 2 pixel width.
// This will be used as a minimum width for any bar section, and will
// ensure that a section is always displayed at least 1 pixel wide.
// (FillRect will output 1 pixel less than the rect's width)
//
pt[0].x = 0 ;
pt[0].y = 0 ;
pt[1].x = 1 ;
pt[1].y = 0 ;
DPtoLP (ps.hdc, &pt[0], 2) ;
nMinWidth = max ((pt[1].x - pt[0].x), 1) ;
xBar[0] = 50;
xBar[1] = xBar[0] + max ( (int)dPercentStaticData, nMinWidth);
xBar[2] = xBar[1] + max ( (int)dPercentStackMax , nMinWidth);
xBar[3] = xBar[2] + max ( (int)dPercentFixed , nMinWidth);
xBar[4] = xBar[3] + max ( (int)dPercentMoveable , nMinWidth);
xBar[5] = xBar[4] + max ( (int)dPercentFree , nMinWidth);
xBar[6] = xBar[5] + max ( (int)dPercentOther , nMinWidth);
xBar[7] = xBar[6] + max ( (int)dPercentUnused , nMinWidth);
yBar[0] = 20;
yBar[1] = 30;
/* Active window's Caption */
if (IsWindow (DDS.hwndActive))
{
char szText [65],
szCaption [40];
BOOL bTruncate = (GetWindowTextLength (DDS.hwndActive) > 39);
int cch;
cch = GetWindowText (DDS.hwndActive, szCaption, 39);
szCaption [cch] = '\0';
if (bTruncate) strcpy (&szCaption [36], "...");
wsprintf (szText, "%.39s [hInstance = %4.4X]", (LPSTR) szCaption,
DDS.hinstActive);
SetTextAlign (ps.hdc, TA_BOTTOM);
TextOut (ps.hdc, 250, 18, szText, strlen (szText) );
SetTextAlign (ps.hdc, TA_TOP);
}
/* label at left end */
lTextExt = GetTextExtent (ps.hdc,"0", 1);
wTextWidth = LOWORD (lTextExt);
TextOut (ps.hdc, (xBar[0]-wTextWidth-10), yBar[0] + 2, "0", strlen("0") );
/* label at right end */
TextOut (ps.hdc, (xBar[7]+10), yBar[0] + 2, "64K", 3);
for (i=0; i<=6; i++)
{
POINT ptA, ptB, ptC, ptD;
RECT rect;
char sz [40];
ptA.x = (xBar[i+1] + xBar[i])/2 ;
if ((xBar[i+1] - xBar[i]) <= (3*nMinWidth)/2 ) ptA.x = xBar[i] ;
ptA.y = yBar[1] ;
ptB.x = ptA.x ;
ptB.y = 120 - (10*i) ;
ptC.x = ptB.x + 20 ;
ptC.y = ptB.y ;
ptD.x = ptC.x + 10 ;
ptD.y = ptC.y - 4 ;
rect.left = xBar [i] ;
rect.top = yBar [0] ;
rect.right = xBar [i+1];
rect.bottom = yBar [1] ;
FillRect (ps.hdc, &rect, hbr[i]);
MoveTo (ps.hdc, ptA.x, ptA.y);
LineTo (ps.hdc, ptB.x, ptB.y);
LineTo (ps.hdc, ptC.x, ptC.y);
switch (i)
{
case 0: wsprintf (sz, "static data (%u)", DDS.wStaticData); break;
case 1: wsprintf (sz, "stack allocated (%u), used (%u)",
DDS.wStackMax, DDS.wStackUsed); break;
case 2: wsprintf (sz, "fixed heap (%u)", DDS.wHeapFixed); break;
case 3: wsprintf (sz, "moveable heap (%u)", DDS.wHeapMoveable);break;
case 4: wsprintf (sz, "free heap (%u)", DDS.wHeapFree); break;
case 5: wsprintf (sz, "other (%u)", DDS.wOther); break;
case 6: wsprintf (sz, "room to grow (%u)", DDS.wUnused); break;
}
TextOut (ps.hdc, ptD.x, ptD.y, sz, strlen(sz));
}
SelectObject (ps.hdc, (HBRUSH)GetStockObject (NULL_BRUSH));
Rectangle (ps.hdc, xBar[0], yBar[0], xBar[7], yBar[1]);
}
EndPaint (DDS.hwndClient, &ps);
}
void dds_walk ()
{
static DEFAULTDATASEGMENT OldDDS;
WORD wRecordSize, // size in bytes of heap record.
wStatus; // type of heap record.
LPSTR lpInstance, // far pointer to Default Data Segment.
lpHeapRecord, // far pointer to heap record.
lpNextHeapRecord; // far pointer to next heap record.
#define PREV_POINTER (*(WORD FAR*) lpHeapRecord) // Backward "pointer"
#define NEXT_POINTER (*(WORD FAR*)(lpHeapRecord+2)) // Forward "pointer"
#define PSTACKBOTTOM (*(WORD FAR*)(lpInstance+14))
#define PSTACKMIN (*(WORD FAR*)(lpInstance+12))
#define PSTACKTOP (*(WORD FAR*)(lpInstance+10))
#define PLOCALHEAP (*(WORD FAR*)(lpInstance+ 6))
// First, initialize the data segment values.
//
//
DDS.wSize = 0;
DDS.wStaticData = 0;
DDS.wStackMax = 0;
DDS.wStackUsed = 0;
DDS.wHeapMoveable = 0;
DDS.wHeapFixed = 0;
DDS.wHeapFree = 0;
DDS.wOther = 0;
DDS.wUnused = 0;
// Now, get the window that has the focus.
//
//
DDS.hwndActive = GetActiveWindow ();
// Is it a valid window?
//
//
if ( !IsWindow (DDS.hwndActive) ) return;
// If this is a different window than before,
// get a new instance handle.
//
//
if (DDS.hwndActive != OldDDS.hwndActive)
{
DDS.hinstActive = (HANDLE) GetWindowWord (DDS.hwndActive,
GWW_HINSTANCE);
if (!DDS.hinstActive) return;
}
// Lock down the Data Segment
//
//
if ( !(lpInstance = GlobalLock (DDS.hinstActive))) return;
/*
* The Data Segment is a global memory object - created by WINDOWS
* with a GlobalAlloc. It's comprised of 4 components: header,
* Static, stack, and local heap. All 4 components are offset
* into the segment, with the header at DS:0000.
*
*
* The header occupies the first 16 bytes of a Default Data Segment.
* Within the Header area are 3 pointers to the stack:
*
* pStackBottom - (highest physical address) beginning of stack.
* pStackMin - High-Water mark of actual stack use.
* pStackTop - (lowest physical address) end of stack.
*
* Remember, the stack grows "down" (higher to lower address), so
* to compute the stack sizes, we use these equations:
*
* wStackMax = pStackBottom - pStackTop ;
* wStackUsed = pStackBottom - pStackMin ;
*
*
*/
DDS.wStackMax = PSTACKBOTTOM - PSTACKTOP ;
DDS.wStackUsed = PSTACKBOTTOM - PSTACKMIN ;
DDS.wStaticData = PSTACKTOP ;
/*
* First test for a heap. (It's possible there isn't one.)
*
*/
if (PLOCALHEAP == 0)
{
GlobalUnlock (DDS.hinstActive);
return;
}
/*
* The heap begins where the
* stack ends. The offset that represents the
* beginning of the heap is stored in the header area, 6 bytes from
* DS:0000. Actually, the heap begins 4 bytes before this offset.
*
* Now we'll get a far pointer (lpHeapRecord) to the 1st record in the
* heap.
*/
lpHeapRecord = lpInstance + PLOCALHEAP - 4;
/*
* Traverse the local heap. The heap is implemented as a doubly-linked
* list. The 1st WORD is a backward "pointer" (ie, offset) to the
* previous record. The 2nd WORD is the forward pointer to the next
* record. When the forward pointer points to itself we are done.
*
*/
DDS.wSize = GlobalSize (DDS.hinstActive);
while (FP_OFF(lpHeapRecord) < DDS.wSize)
{
lpNextHeapRecord = (lpInstance + NEXT_POINTER);
if (lpNextHeapRecord == lpHeapRecord) break;
wRecordSize = lpNextHeapRecord - lpHeapRecord; //includes ptr overhead
wStatus = (PREV_POINTER & 0x0003);
switch (wStatus)
{
case 0: DDS.wHeapFree += wRecordSize; break;
case 1: DDS.wHeapFixed += wRecordSize; break;
case 2:
case 3: DDS.wHeapMoveable += wRecordSize; break;
}
lpHeapRecord = lpNextHeapRecord;
}
/*
* At this point, heap traversal is done.
* However, the heap can grow until the size of DS is 64K (0xFFFF).
* Determine how many additional bytes the heap can grow.
*
*/
DDS.wUnused = 0xFFFF - DDS.wSize;
/*
* Anything else we didn't account for?
*
*/
DDS.wOther = DDS.wSize - DDS.wStaticData
- DDS.wStackMax
- DDS.wHeapFixed
- DDS.wHeapFree
- DDS.wHeapMoveable ;
GlobalUnlock (DDS.hinstActive);
// If anything has changed since last walk, update client window.
//
if (DDS.hwndActive != OldDDS.hwndActive ||
DDS.wHeapFree != OldDDS.wHeapFree ||
DDS.wHeapFixed != OldDDS.wHeapFixed ||
DDS.wHeapMoveable != OldDDS.wHeapMoveable ||
DDS.wOther != OldDDS.wOther ||
DDS.wSize != OldDDS.wSize ||
DDS.wStackUsed != OldDDS.wStackUsed)
{
InvalidateRect (DDS.hwndClient, NULL, TRUE);
UpdateWindow (DDS.hwndClient);
OldDDS = DDS;
}
}